/**
 @file HashSet.h
 @author Danciu Alin
 @brief This header file contains thee structures and functions needed to work
 with hash sets.

 It contains functions for creating ,destroying ,adding an element, removing an element, finding a key, finding a value, seting a value
 */

#ifndef HASHSET_H_
#define HASHSET_H_ 

struct hpair_adt;
struct hash_adt;

/**
 @brief functions used for dispersion
 there are currently 2 functions used for this. The functions are selected at creation time. If no selection is made a default value is assumed
 refer to H_new(...) also. Currently this are used internally in funtion H_hash
*/

/**
 @brief TypeKey type of key used in dispersion. This implementation uses int
*/
typedef int TypeKey;

/**
 @brief HashSet representation of the main structure
*/
typedef struct hash_adt * HashSet;

/**
 @brief HashPair representation of the structure (key,value)
*/
typedef struct hpair_adt * HashPair;

/**
 @brief H_hash
 returns a hash value for the parameter
*/
TypeKey H_hash(HashSet h, TypeKey n);


/**
 *public functions
*/

/**
 @brief H_New creates a new HashSet using default dispersion function and a predefined linear capacity
*/
HashSet H_New();

/**
 @brief H_New creates a new HashSet using function specified with predefined linear capacity
 @param f_type is one of H_DFmod | H_DFmul
*/
HashSet H_New(char f_type);

/**
 @brief H_New creates a new HashSet with predefined function
 @param n is an aproximation of the number of elements that the HashSet will contain
*/
HashSet H_New(long int n);

/**
 @brief H_New combination of the two H_new functions above. Use this whenever possible to improve performance
*/
HashSet H_New(char f_type, long int n);

/**
 @brief H_Free destroys the HashSet, freeing all the memory
 @param h the HashSet
*/
void H_Free(HashSet h);

/**
 @brief H_Add adds the pair (key,value) to h, if the (key) is not in the HashSet, has no effect otherwise
 @param h the HashSet
 @param key the key in pair (key,value)
 @param value the value in pair (key,value)
*/
void H_Add(HashSet h, TypeKey key, void * value);

/**
 @brief H_Del deletes the pair (key,value) from h, if there is such pair, has no effect otherwise
 @param h the HashSet from where the pair is deleted
 @param key the key in pair (key,value)
*/
void H_Del(HashSet h, TypeKey key);

/**
 @brief H_Find searches for a key in the HashTable
 @param h the HashSet
 @param key the key
 @return an int with value 1 if key is in h, an int with value 0 otherwise
*/
int H_Find(HashSet h, TypeKey key);

/**
 @brief H_Get gets a key by value
 @param h the HashSet
 @param key the key in pair (key,value)
 @return if H_Find(h, key) is 1 then the value in pair (key,value) else NULL
*/
void * H_Get(HashSet h, TypeKey key);

/**
 @brief H_Set sets the value form pair (key,value) to nval if key is in h, has no effect otherwise
 @param h the HashSet
 @param key eht key in pair (key,value)
 @param nvalue the new value to be set
*/
void H_Set(HashSet h, TypeKey key, void * nvalue);

#endif /*HASHSET_H_*/ 